其他
Weblogic安全漫谈(二)
前言
README.txt
走就行,注意一点是要改一下bsu.sh
中的内存限制,不然会遇到Java heap space OutOfMemoryError
。unzip p21984589_1036_Generic.zip -d /u01/app/oracle/middleware/utils/bsu/cache_dir/
cd /u01/app/oracle/middleware/utils/bsu/
sed -i 's/512/1024/' bsu.sh
./bsu.sh -install -patch_download_dir=/u01/app/oracle/middleware/utils/bsu/cache_dir -patchlist=S8C2 -prod_dir=/u01/app/oracle/middleware/wlserver
. /u01/app/oracle/middleware/wlserver/server/bin/setWLSEnv.sh
/java/bin/java weblogic.version
ServerChannelInputStream#resolveClass
中新增了类名黑名单,加入了CC链比较关键的包。1. 原生反序列化依然存在,流程中的各个关键方法可用。 2. CC链在黑名单以外的部分,仍然可以用作调用链。 3. 黑名单类不在 ServerChannelInputStream
做反序列化就不受限制。
readObject
的地方,用Serializable.class.isAssignableFrom(clazz)
筛出可被序列化的类,筛出数据可控的二次反序列化。找到的两个可用类刚好对应两个CVE。CVE-2016-0638
weblogic.jms.common.StreamMessageImpl#readExternal
,完成父类readExternal
后读到的字节是十进制1时会进入存在readObject
的分支。createPayload
方法,读到的整数大于CHUNK_LINK_THRESHOLD
会做一些处理。中间这块的处理看不太懂,我们假设它不满足判断继续往后走,一直跟到Chunk.createOneSharedChunk
。Chunk
的判断和操作由于笔者太菜了看不懂,但到了这里就能看出,这个先前读到的被一路传过来的整数是后段数据长度。后面这段数据被完整读出并封装赋值给this.payload
,随后进行第二次反序列化。StreamMessageImpl
的writeExternal
,写入相应格式的CC链序列化payload,再经过一次正常新建类对象并经过第二次序列化,最后用上一篇的EXP打出去就行。readExternal:1433, StreamMessageImpl (weblogic.jms.common)
readExternalData:1814, ObjectInputStream (java.io)
readOrdinaryObject:1773, ObjectInputStream (java.io)
resolveClass:110, InboundMsgAbbrev$ServerChannelInputStream (weblogic.rjvm)
readNonProxyDesc:1589, ObjectInputStream (java.io)
readClassDesc:1494, ObjectInputStream (java.io)
readOrdinaryObject:1748, ObjectInputStream (java.io)
readObject0:1327, ObjectInputStream (java.io)
CVE-2016-3510
weblogic.corba.utils.MarshalledObject#readResolve
,是比上一个品相更好的二次反序列化类。this.objBytes
属性来自构造函数传入的对象,直接将payload对象作为参数给进去就行。readResolve:58, MarshalledObject (weblogic.corba.utils)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:39, NativeMethodAccessorImpl (sun.reflect)
invoke:25, DelegatingMethodAccessorImpl (sun.reflect)
invoke:597, Method (java.lang.reflect)
invokeReadResolve:1056, ObjectStreamClass (java.io)
readOrdinaryObject:1784, ObjectInputStream (java.io)
readObject0:1327, ObjectInputStream (java.io)
CVE-2017-3248
CVE-2018-2628
ysoserial
的RMIRegistryExploit
设计用于攻击Java原生RMI注册端,用了给JRMPClient
的payload套上Registry动态代理的方式,来兼容Java原生registry.bind方法的参数要求。InboundMsgAbbrev
重写resolveProxyClass
作为CVE-2017-3248的修复方式原因之一。我们是用自己的EXP作为T3客户端,不存在参数类型兼容的问题,直接去掉动态代理类的包装即可绕过检查(或者使用不同的接口代理)。CVE-2018-2893
cpuapr2018
补丁中黑名单新增了sun.rmi.server.UnicastRef
。看到java.rmi.server.RemoteObjectInvocationHandler
会使用父类的RemoteObject
,读到refClassName
时就会做一次神奇的第二次反序列化,自带绕过特效。MarshalledObject
被去掉了Serializable接口,StreamMessageImpl
则仍然可用于绕过。CVE-2018-3245
cpujul2018
补丁中黑名单继续增加了:java.rmi.activation
sun.rmi.server
java.rmi.server.UnicastRemoteObject
java.rmi.server.RemoteObjectInvocationHandler
RemoteObject
不在黑名单的子类们仍然可用,直到cpuoct2018
将基类纳入黑名单。参考链接
[2] Weblogic JRMP反序列化漏洞回顾: https://xz.aliyun.com/t/2479